package com.alibaba.citrus.cr.unified.inventory.handler;

import com.alibaba.citrus.cr.common.util.OpenApiUtils;
import com.alibaba.citrus.cr.unified.inventory.model.openapi.FulfillmentOrderOpenApiResponseResult;
import com.alibaba.citrus.cr.unified.inventory.utils.AllocateOpenApiUtil;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.*;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.Result;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentOrderDetailOpenApiResponse;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentOrderDetailResponse;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentOrderOpenApiResponse;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentOrderResponse;
import com.alibaba.cz.base.tool.DateFormatUtil;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;

/**
 * @description:
 * @author: yuhw
 * @date: 2024年03月15日 15:37
 **/
@Component
public class FulfillmentOrderOpenApi {
    private static Log log = Log.getLogger(FulfillmentOrderOpenApi.class);

    private static final String TRUE = "1";
    private static final String FALSE = "0";
    private static final String ZERO = "0";
    //正向履约单
    private static final String CREATE_ORDER_URL = "/fulfillment-center/delivery/dubbo/api/fulfillment/createOrder";
    //逆向履约单
    private static final String CREATE_REVERSE_ORDER_URL = "/fulfillment-center/delivery/dubbo/api/fulfillment/createReverseOrder";

//    @Resource
//    private OpenApiUtils openApiUtils;
    @Resource
    private AllocateOpenApiUtil allocateOpenApiUtil;

    /**
     * 创建正向履约单  出入参 全部为内部dubbo
     * @param request
     * @return
     */
    public Result<FulfillmentOrderResponse> createOrder(CreateFulfillmentOrderReq request){
        CreateFulfillmentOrderOpenApiReq apiReq = buildCreateFulfillmentOrderOpenApiReq(request);
        Result<FulfillmentOrderOpenApiResponse> createOrder = createOrder(apiReq);
        Result<FulfillmentOrderResponse> responseResult = buildFulfillmentOrderResponseResult(createOrder);
        return responseResult;
    }

    /**
     *  创建正向履约单 openAPI入参
     */
    public Result<FulfillmentOrderOpenApiResponse> createOrder(CreateFulfillmentOrderOpenApiReq request){
        log.info("FulfillmentOrderOpenApi_createOrder_request:{}",JSON.toJSONString(request));
        //这里的result对象需要拷贝过来转换下.
        ResponseEntity<FulfillmentOrderOpenApiResponseResult> result = null;
        try{
            result = allocateOpenApiUtil.post(CREATE_ORDER_URL, JSON.toJSON(request), FulfillmentOrderOpenApiResponseResult.class);
        }catch (Throwable e){
            log.error("FulfillmentOrderOpenApi_createOrder_error",e);
            int retryTimes = 0;
            while (retryTimes < 3){
                try {
                    result = allocateOpenApiUtil.post(CREATE_ORDER_URL, JSON.toJSON(request), FulfillmentOrderOpenApiResponseResult.class);
                    break;
                }catch (Throwable throwable){
                    log.error("FulfillmentOrderOpenApi_createOrder_retry_error",throwable);
                    retryTimes++;
                }
            }
        }
        log.info("FulfillmentOrderOpenApi_createOrder_result:{}",JSON.toJSONString(result));
        Result<FulfillmentOrderOpenApiResponse> response = JSONObject.parseObject(JSON.toJSONString(result.getBody()), new TypeReference<Result<FulfillmentOrderOpenApiResponse>>() {

        });
        log.info("FulfillmentOrderOpenApi_createOrder_response:{}",JSON.toJSONString(response));
        return response;
    }

    /**
     * 创建逆向履约单  出入参 全部为内部dubbo
     */
    public Result<FulfillmentOrderResponse> createReverseOrder(CreateFulfillmentOrderReq request){
        CreateReverseFulfillmentOrderOpenApiReq apiReq = buildCreateReverseFulfillmentOrderOpenApiReq(request);
        Result<FulfillmentOrderOpenApiResponse> createOrder = createReverseOrder(apiReq);
        Result<FulfillmentOrderResponse> responseResult = buildFulfillmentOrderResponseResult(createOrder);
        return responseResult;
    }

    public Result<FulfillmentOrderOpenApiResponse> createReverseOrder(CreateReverseFulfillmentOrderOpenApiReq request){
        log.info("FulfillmentOrderOpenApi_createReverseOrder_request:{}",JSON.toJSONString(request));
        ResponseEntity<FulfillmentOrderOpenApiResponseResult> result = null;
        try {
            result = allocateOpenApiUtil.post(CREATE_REVERSE_ORDER_URL, JSON.toJSON(request), FulfillmentOrderOpenApiResponseResult.class);
        }catch (Throwable e){
            log.error("FulfillmentOrderOpenApi_createReverseOrder_error",e);
            int retryTimes = 0;
            while (retryTimes < 3){
                try {
                    result = allocateOpenApiUtil.post(CREATE_ORDER_URL, JSON.toJSON(request), FulfillmentOrderOpenApiResponseResult.class);
                    break;
                }catch (Throwable throwable){
                    log.error("FulfillmentOrderOpenApi_createReverseOrder_retry_error",throwable);
                    retryTimes++;
                }
            }
        }
        log.info("FulfillmentOrderOpenApi_createOrder_result:{}",JSON.toJSONString(result));
        Result<FulfillmentOrderOpenApiResponse> response = JSONObject.parseObject(JSON.toJSONString(result.getBody()), new TypeReference<Result<FulfillmentOrderOpenApiResponse>>() {

        });
        log.info("FulfillmentOrderOpenApi_createReverseOrder_response:{}",JSON.toJSONString(response));
        return response;
    }


    public CreateFulfillmentOrderOpenApiReq buildCreateFulfillmentOrderOpenApiReq(CreateFulfillmentOrderReq req){
        CreateFulfillmentOrderOpenApiReq apiReq = new CreateFulfillmentOrderOpenApiReq();
        BeanUtils.copyProperties(req,apiReq);
        apiReq.setRequestNo(req.getRequestNo());
        apiReq.setFromSys(req.getFromSys());
        apiReq.setBusinessType(req.getBusinessType());
        apiReq.setBusinessUnitCode(req.getBusinessUnitCode());
        apiReq.setSourceOrderNo(req.getSourceOrderNo());
        apiReq.setRefOrderType(req.getRefOrderType());
        apiReq.setFulfillmentType(req.getFulfillmentType() == null ? null : req.getFulfillmentType().toString());
        apiReq.setAutoSubmit(Boolean.TRUE.equals(req.getAutoSubmit()) ? FulfillmentOrderOpenApi.TRUE : FulfillmentOrderOpenApi.FALSE);
        apiReq.setPriority(req.getPriority());
        apiReq.setLogicShippingWarehouseCode(req.getLogicShippingWarehouseCode());
        apiReq.setLogicReceivingWarehouseCode(req.getLogicReceivingWarehouseCode());
        apiReq.setSoldToPartyCode(req.getSoldToPartyCode());
        apiReq.setShipToPartyCode(req.getShipToPartyCode());
        //TODO 没有透出 features
        apiReq.setProductGroupCode(req.getProductGroupCode());
        apiReq.setChannelCode(req.getChannelCode());
        apiReq.setSalesOrganizationCode(req.getSalesOrganizationCode());
        if (StringUtils.isNotBlank(req.getExpectedDeliveryTime())){
            //TODO 非必填 可考虑去掉
            apiReq.setExpectedDeliveryDate(DateFormatUtil.formatToyyyMMdd(DateFormatUtil.parseSimpleDateFormat(req.getExpectedDeliveryTime())));
        }
//        apiReq.setCreator(StringUtils.isNotBlank(req.getCreator()) ? req.getCreator() : "sap");
        apiReq.setCreator("system");
        apiReq.setShippingMethodCode(StringUtils.isNotBlank(req.getShippingMethodCode()) ? ZERO + req.getShippingMethodCode() : null);
        apiReq.setRemark(req.getRemark());

        List<CreateFulfillmentOrderDetailOpenApiDTO> apiDetailList = Lists.newArrayList();
//        Nullable.stream(req.getDetailList()).forEach(detail -> apiDetailList.add(buildCreateFulfillmentOrderDetailOpenApiDTO(detail)));
        Nullable.stream(req.getDetailList()).map(FulfillmentOrderOpenApi::buildCreateFulfillmentOrderDetailOpenApiDTO)
                .forEach(apiDetailList::add);
        apiReq.setDetailList(apiDetailList);
        return apiReq;
    }

    private static CreateFulfillmentOrderDetailOpenApiDTO buildCreateFulfillmentOrderDetailOpenApiDTO(CreateFulfillmentOrderDetailDTO detail){
        CreateFulfillmentOrderDetailOpenApiDTO apiDetail = new CreateFulfillmentOrderDetailOpenApiDTO();
        BeanUtils.copyProperties(detail,apiDetail);
        apiDetail.setSourceOrderLineNo(detail.getSourceOrderLineNo());
        apiDetail.setRefOrderLineNo(detail.getRefOrderLineNo());
        apiDetail.setMaterialCode(detail.getMaterialCode());
        apiDetail.setRefOrderCreateTime(detail.getRefOrderCreateTime());
        apiDetail.setProductionDate(detail.getProductionDate());
        apiDetail.setSalesUnitCode(detail.getSalesUnitCode());
        apiDetail.setSaleQuantity(Optional.ofNullable(detail.getSaleQuantity()).map(BigDecimal::intValue).map(String::valueOf).orElse(null));
        apiDetail.setQuantity(Optional.ofNullable(detail.getQuantity()).map(BigDecimal::toString).orElse(null));
        apiDetail.setShippingUnitCode(detail.getShippingUnitCode());
        apiDetail.setRemark(detail.getRemark());
        return apiDetail;
    }

    /**
     *  请求 逆向内部dubbo -> openAPi
     * @param req
     * @return
     */
    private static CreateReverseFulfillmentOrderOpenApiReq buildCreateReverseFulfillmentOrderOpenApiReq(CreateFulfillmentOrderReq req){
        CreateReverseFulfillmentOrderOpenApiReq apiReq = new CreateReverseFulfillmentOrderOpenApiReq();
        BeanUtils.copyProperties(req,apiReq);
        apiReq.setRequestNo(req.getRequestNo());
        apiReq.setSourceOrderNo(req.getSourceOrderNo());
        apiReq.setRefOrderType(req.getRefOrderType());
        apiReq.setFulfillmentType(Optional.ofNullable(req.getFulfillmentType()).map(String::valueOf).orElse(null));
        apiReq.setPriority(req.getPriority());
        apiReq.setLogicShippingWarehouseCode(req.getLogicShippingWarehouseCode());
        apiReq.setProductGroupCode(req.getProductGroupCode());
        apiReq.setChannelCode(req.getChannelCode());
        apiReq.setSalesOrganizationCode(req.getSalesOrganizationCode());
        apiReq.setShipToPartyCode(req.getShipToPartyCode());
        apiReq.setSoldToPartyCode(req.getSoldToPartyCode());
        apiReq.setLogicReceivingWarehouseCode(req.getLogicReceivingWarehouseCode());
//        apiReq.setCreator(StringUtils.isBlank(req.getCreator()) ? "sap" : req.getCreator());
        apiReq.setCreator("system");
        if (StringUtils.isNotBlank(req.getExpectedDeliveryTime())){
            apiReq.setExpectedDeliveryDate(DateFormatUtil.formatToyyyMMdd(DateFormatUtil.parseSimpleDateFormat(req.getExpectedDeliveryTime())));
        }
        apiReq.setShippingMethodCode(StringUtils.isNotBlank(req.getShippingMethodCode()) ? ZERO + req.getShippingMethodCode() :null);
        apiReq.setRemark(req.getRemark());
        apiReq.setExpectedArrivalTime(req.getExpectedArrivalTime());
        apiReq.setShipOrderNo(req.getShipOrderNo());
        apiReq.setContainerNo(req.getContainerNo());
        apiReq.setDiverMobile(req.getDiverMobile());
        apiReq.setAutoSubmit(Boolean.TRUE.equals(req.getAutoSubmit()) ? FulfillmentOrderOpenApi.TRUE : FulfillmentOrderOpenApi.FALSE);
        List<CreateFulfillmentOrderDetailOpenApiDTO> apiDetailList = Lists.newArrayList();
        Nullable.stream(req.getDetailList()).map(FulfillmentOrderOpenApi::buildCreateFulfillmentOrderDetailOpenApiDTO)
                .forEach(apiDetailList::add);
        apiReq.setDetailList(apiDetailList);
        return apiReq;
    }

    /**
     * 响应 openAPI -> 内部dubbo
     */
    private Result<FulfillmentOrderResponse> buildFulfillmentOrderResponseResult(Result<FulfillmentOrderOpenApiResponse> result){
        if (result == null){
            return null;
        }
        Result<FulfillmentOrderResponse> responseResult = new Result<>();
        responseResult.setSuccess(result.isSuccess());
        responseResult.setTotal(result.getTotal());
        responseResult.setMessage(result.getMessage());
        responseResult.setErrorCode(result.getErrorCode());
        responseResult.setResult(buildFulfillmentOrderResponse(result.getResult()));
        return responseResult;
    }

    private FulfillmentOrderResponse buildFulfillmentOrderResponse(FulfillmentOrderOpenApiResponse response){
        if (response == null){
            return null;
        }
        FulfillmentOrderResponse orderResponse = new FulfillmentOrderResponse();
        orderResponse.setFulfillmentOrderNo(response.getFulfillmentOrderNo());
        orderResponse.setSourceOrderNo(response.getSourceOrderNo());
        List<FulfillmentOrderDetailResponse> detailResponses = Lists.newArrayList();
        Nullable.stream(response.getDetailList()).map(FulfillmentOrderOpenApi::buildFulfillmentOrderDetailOpenApiResponse)
                .forEach(detailResponses::add);
        orderResponse.setFulfillmentOrderDetailList(detailResponses);
        return orderResponse;
    }

    /**
     * 响应明细转换
     */
    private static FulfillmentOrderDetailResponse buildFulfillmentOrderDetailOpenApiResponse(FulfillmentOrderDetailOpenApiResponse response){
        if (response == null){
            return null;
        }
        FulfillmentOrderDetailResponse detailResponse = new FulfillmentOrderDetailResponse();
        detailResponse.setSourceOrderLineNo(response.getSourceOrderLineNo());
        detailResponse.setLineNumber(response.getLineNumber());
        return detailResponse;
    }

}
